/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2009 - 2012 Luca Mingardi.
 *
 * This file is part of jeeObserver.
 *
 * JeeObserver is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * JeeObserver is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */
package jeeobserver.server.database;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.logging.Level;
import jeeobserver.ActionCoreElement;
import jeeobserver.HardDiskCoreElement;
import jeeobserver.HttpSessionCoreElement;
import jeeobserver.JvmCoreElement;
import jeeobserver.server.ActionParameters;
import jeeobserver.server.ActionStatistics;
import jeeobserver.server.HardDiskParameters;
import jeeobserver.server.HardDiskStatistics;
import jeeobserver.server.HttpSessionParameters;
import jeeobserver.server.HttpSessionStatistics;
import jeeobserver.server.JeeObserverServerContext;
import jeeobserver.server.JvmParameters;
import jeeobserver.server.JvmStatistics;
import jeeobserver.server.RequestParameter;
import jeeobserver.server.Statistics.DateStatistics;
import jeeobserver.server.Statistics.NumberStatistics;
import jeeobserver.server.Statistics.SamplingStatistics;
import jeeobserver.settings.Settings;

/**
 * The Class DefaultDatabaseHandler.
 *
 * @author Luca Mingardi
 * @version 4.0
 */
public class FileDatabaseHandler implements DatabaseHandler {

	public static final String TIMER_TASK_NAME = "JOS_TIMER_TASK";

	/** The Constant DATABASE_PATH_PARAMETER. */
	public static final String PATH_PARAMETER = "JOS_DATABASE_PATH";

	/** The Constant ACTION_SAMPLING_PERIOD_PARAMETER. */
	public static final String ACTION_SAMPLING_PERIOD_PARAMETER = "JOS_DATABASE_ACTION_SAMPLING_PERIOD";

	/** The Constant HTTP_SESSION_SAMPLING_PERIOD_PARAMETER. */
	public static final String HTTP_SESSION_SAMPLING_PERIOD_PARAMETER = "JOS_DATABASE_HTTP_SESSION_SAMPLING_PERIOD";

	/** The Constant JVM_SAMPLING_PERIOD_PARAMETER. */
	public static final String JVM_SAMPLING_PERIOD_PARAMETER = "JOS_DATABASE_JVM_SAMPLING_PERIOD";

	/** The Constant HARD_DISK_SAMPLING_PERIOD_PARAMETER. */
	public static final String HARD_DISK_SAMPLING_PERIOD_PARAMETER = "JOS_DATABASE_HARD_DISK_SAMPLING_PERIOD";

	/** The Constant SAMPLING_PERIOD_MILLISECOND. */
	public static final int SAMPLING_PERIOD_MILLISECOND = RequestParameter.SAMPLING_PERIOD_MILLISECOND;

	/** The Constant SAMPLING_PERIOD_SECOND. */
	public static final int SAMPLING_PERIOD_SECOND = RequestParameter.SAMPLING_PERIOD_SECOND;

	/** The Constant SAMPLING_PERIOD_MINUTE. */
	public static final int SAMPLING_PERIOD_MINUTE = RequestParameter.SAMPLING_PERIOD_MINUTE;

	/** The Constant SAMPLING_PERIOD_HOUR. */
	public static final int SAMPLING_PERIOD_HOUR = RequestParameter.SAMPLING_PERIOD_HOUR;

	/** The Constant SAMPLING_PERIOD_DAY. */
	public static final int SAMPLING_PERIOD_DAY = RequestParameter.SAMPLING_PERIOD_DAY;

	/** The Constant DATABASE_PATH_PARAMETER. */
	public static final String DEFAULT_PATH = "JEEOBSERVER_SERVER_" + JeeObserverServerContext.VERSION[0] + "_" + JeeObserverServerContext.VERSION[1];

	/** The Constant DEFAULT_ACTION_SAMPLING_PERIOD. */
	public static final int DEFAULT_ACTION_SAMPLING_PERIOD = SAMPLING_PERIOD_MINUTE;

	/** The Constant DEFAULT_ACTION_SAMPLING_PERIOD. */
	public static final int DEFAULT_JVM_SAMPLING_PERIOD = SAMPLING_PERIOD_MINUTE;

	/** The Constant DEFAULT_ACTION_SAMPLING_PERIOD. */
	public static final int DEFAULT_HTTP_SESSION_SAMPLING_PERIOD = SAMPLING_PERIOD_HOUR;

	/** The Constant DEFAULT_ACTION_SAMPLING_PERIOD. */
	public static final int DEFAULT_HARD_DISK_SAMPLING_PERIOD = SAMPLING_PERIOD_MINUTE;

	private Timer timer;

	private FileHardDiskHandler hardDiskDatabaseHandler;

	private FileHttpSessionHandler httpSessionDatabaseHandler;

	private FileJvmHandler jvmDatabaseHandler;

	private FileActionHandler actionDatabaseHandler;

	private FileSettingsHandler settingsDatabaseHandler;

	public FileDatabaseHandler(Map<String, String> parameters) throws DatabaseException {

		// Start timer task
		this.timer = new Timer(FileDatabaseHandler.TIMER_TASK_NAME, true);
		this.timer.schedule(new DatabaseHandlerTimerTask(), DatabaseHandlerTimerTask.TIMER_INTERVAL, DatabaseHandlerTimerTask.TIMER_INTERVAL);

		String path = FileDatabaseHandler.DEFAULT_PATH;
		if (parameters != null && parameters.containsKey(FileDatabaseHandler.PATH_PARAMETER)) {
			path = parameters.get(FileDatabaseHandler.PATH_PARAMETER);
		} else {
			JeeObserverServerContext.logger.log(Level.WARNING, "Parameter " + FileDatabaseHandler.PATH_PARAMETER + " not found, using default {0}.", FileDatabaseHandler.DEFAULT_PATH);
		}


		final Set<Integer> samplingPeriods = new HashSet<Integer>();
		samplingPeriods.add(FileDatabaseHandler.SAMPLING_PERIOD_SECOND);
		samplingPeriods.add(FileDatabaseHandler.SAMPLING_PERIOD_MINUTE);
		samplingPeriods.add(FileDatabaseHandler.SAMPLING_PERIOD_HOUR);
		samplingPeriods.add(FileDatabaseHandler.SAMPLING_PERIOD_DAY);

		int actionSamplingPeriod = FileDatabaseHandler.SAMPLING_PERIOD_MINUTE;

		int jvmSamplingPeriod = FileDatabaseHandler.SAMPLING_PERIOD_MINUTE;

		int httpSessionSamplingPeriod = FileDatabaseHandler.SAMPLING_PERIOD_HOUR;

		int hardDiskSamplingPeriod = FileDatabaseHandler.SAMPLING_PERIOD_MINUTE;


		if (parameters.containsKey(FileDatabaseHandler.ACTION_SAMPLING_PERIOD_PARAMETER)) {
			try {
				if (samplingPeriods.contains(Integer.parseInt(parameters.get(FileDatabaseHandler.ACTION_SAMPLING_PERIOD_PARAMETER)))) {
					actionSamplingPeriod = Integer.parseInt(parameters.get(FileDatabaseHandler.ACTION_SAMPLING_PERIOD_PARAMETER));
				} else {
					JeeObserverServerContext.logger.log(Level.SEVERE, "Parameter {0} = {1} is not a valid. (Available values: {2} | {3} | {4} | {5})", new Object[]{FileDatabaseHandler.ACTION_SAMPLING_PERIOD_PARAMETER, parameters.get(FileDatabaseHandler.ACTION_SAMPLING_PERIOD_PARAMETER), FileDatabaseHandler.SAMPLING_PERIOD_SECOND, FileDatabaseHandler.SAMPLING_PERIOD_MINUTE, FileDatabaseHandler.SAMPLING_PERIOD_HOUR, FileDatabaseHandler.SAMPLING_PERIOD_DAY});
				}
			} catch (final NumberFormatException e) {
				JeeObserverServerContext.logger.log(Level.SEVERE, "Parameter " + FileDatabaseHandler.ACTION_SAMPLING_PERIOD_PARAMETER + " = {0} is not a number.", parameters.get(FileDatabaseHandler.ACTION_SAMPLING_PERIOD_PARAMETER));
			}
		} else {
			JeeObserverServerContext.logger.log(Level.FINE, "Parameter " + FileDatabaseHandler.ACTION_SAMPLING_PERIOD_PARAMETER + " not found, using default {0}.", FileDatabaseHandler.DEFAULT_ACTION_SAMPLING_PERIOD);
		}

		if (parameters.containsKey(FileDatabaseHandler.JVM_SAMPLING_PERIOD_PARAMETER)) {
			try {
				if (samplingPeriods.contains(Integer.parseInt(parameters.get(FileDatabaseHandler.JVM_SAMPLING_PERIOD_PARAMETER)))) {
					jvmSamplingPeriod = Integer.parseInt(parameters.get(FileDatabaseHandler.JVM_SAMPLING_PERIOD_PARAMETER));
				} else {
					JeeObserverServerContext.logger.log(Level.SEVERE, "Parameter {0} = {1} is not a valid. (Available values: {2} | {3} | {4} | {5})", new Object[]{FileDatabaseHandler.JVM_SAMPLING_PERIOD_PARAMETER, parameters.get(FileDatabaseHandler.JVM_SAMPLING_PERIOD_PARAMETER), FileDatabaseHandler.SAMPLING_PERIOD_SECOND, FileDatabaseHandler.SAMPLING_PERIOD_MINUTE, FileDatabaseHandler.SAMPLING_PERIOD_HOUR, FileDatabaseHandler.SAMPLING_PERIOD_DAY});
				}
			} catch (final NumberFormatException e) {
				JeeObserverServerContext.logger.log(Level.SEVERE, "Parameter " + FileDatabaseHandler.JVM_SAMPLING_PERIOD_PARAMETER + " = {0} is not a number.", parameters.get(FileDatabaseHandler.JVM_SAMPLING_PERIOD_PARAMETER));
			}
		} else {
			JeeObserverServerContext.logger.log(Level.FINE, "Parameter " + FileDatabaseHandler.JVM_SAMPLING_PERIOD_PARAMETER + " not found, using default {0}.", FileDatabaseHandler.DEFAULT_JVM_SAMPLING_PERIOD);
		}

		if (parameters.containsKey(FileDatabaseHandler.HTTP_SESSION_SAMPLING_PERIOD_PARAMETER)) {
			try {
				if (samplingPeriods.contains(Integer.parseInt(parameters.get(FileDatabaseHandler.HTTP_SESSION_SAMPLING_PERIOD_PARAMETER)))) {
					httpSessionSamplingPeriod = Integer.parseInt(parameters.get(FileDatabaseHandler.HTTP_SESSION_SAMPLING_PERIOD_PARAMETER));
				} else {
					JeeObserverServerContext.logger.log(Level.SEVERE, "Parameter {0} = {1} is not a valid. (Available values: {2} | {3} | {4} | {5})", new Object[]{FileDatabaseHandler.HTTP_SESSION_SAMPLING_PERIOD_PARAMETER, parameters.get(FileDatabaseHandler.HTTP_SESSION_SAMPLING_PERIOD_PARAMETER), FileDatabaseHandler.SAMPLING_PERIOD_SECOND, FileDatabaseHandler.SAMPLING_PERIOD_MINUTE, FileDatabaseHandler.SAMPLING_PERIOD_HOUR, FileDatabaseHandler.SAMPLING_PERIOD_DAY});
				}
			} catch (final NumberFormatException e) {
				JeeObserverServerContext.logger.log(Level.SEVERE, "Parameter " + FileDatabaseHandler.HTTP_SESSION_SAMPLING_PERIOD_PARAMETER + " = {0} is not a number.", parameters.get(FileDatabaseHandler.HTTP_SESSION_SAMPLING_PERIOD_PARAMETER));
			}
		} else {
			JeeObserverServerContext.logger.log(Level.FINE, "Parameter " + FileDatabaseHandler.HTTP_SESSION_SAMPLING_PERIOD_PARAMETER + " not found, using default {0}.", FileDatabaseHandler.DEFAULT_HARD_DISK_SAMPLING_PERIOD);
		}

		if (parameters.containsKey(FileDatabaseHandler.HARD_DISK_SAMPLING_PERIOD_PARAMETER)) {
			try {
				if (samplingPeriods.contains(Integer.parseInt(parameters.get(FileDatabaseHandler.HARD_DISK_SAMPLING_PERIOD_PARAMETER)))) {
					hardDiskSamplingPeriod = Integer.parseInt(parameters.get(FileDatabaseHandler.HARD_DISK_SAMPLING_PERIOD_PARAMETER));
				} else {
					JeeObserverServerContext.logger.log(Level.SEVERE, "Parameter {0} = {1} is not a valid. (Available values: {2} | {3} | {4} | {5})", new Object[]{FileDatabaseHandler.HARD_DISK_SAMPLING_PERIOD_PARAMETER, parameters.get(FileDatabaseHandler.HARD_DISK_SAMPLING_PERIOD_PARAMETER), FileDatabaseHandler.SAMPLING_PERIOD_SECOND, FileDatabaseHandler.SAMPLING_PERIOD_MINUTE, FileDatabaseHandler.SAMPLING_PERIOD_HOUR, FileDatabaseHandler.SAMPLING_PERIOD_DAY});
				}
			} catch (final NumberFormatException e) {
				JeeObserverServerContext.logger.log(Level.SEVERE, "Parameter " + FileDatabaseHandler.HARD_DISK_SAMPLING_PERIOD_PARAMETER + " = {0} is not a number.", parameters.get(FileDatabaseHandler.HARD_DISK_SAMPLING_PERIOD_PARAMETER));
			}
		} else {
			JeeObserverServerContext.logger.log(Level.FINE, "Parameter " + FileDatabaseHandler.HARD_DISK_SAMPLING_PERIOD_PARAMETER + " not found, using default {0}.", FileDatabaseHandler.DEFAULT_HARD_DISK_SAMPLING_PERIOD);
		}



		//Create sub directories
		File pathFolder = new File(path);
		if (!pathFolder.exists()) {
			pathFolder.mkdir();
			JeeObserverServerContext.logger.log(Level.INFO, "Path {0} created because does not exists.", pathFolder.getAbsolutePath());
		}

		File dataFolder = new File(pathFolder.getAbsolutePath() + File.separator + "data");
		if (!dataFolder.exists()) {
			dataFolder.mkdir();
			JeeObserverServerContext.logger.log(Level.FINE, "Path {0} created because does not exists.", dataFolder.getAbsolutePath());
		}

		File settingsFolder = new File(pathFolder.getAbsolutePath() + File.separator + "settings");
		if (!settingsFolder.exists()) {
			settingsFolder.mkdir();
			JeeObserverServerContext.logger.log(Level.FINE, "Path {0} created because does not exists.", settingsFolder.getAbsolutePath());
		}

		File logFolder = new File(pathFolder.getAbsolutePath() + File.separator + "log");
		if (!logFolder.exists()) {
			logFolder.mkdir();
			JeeObserverServerContext.logger.log(Level.FINE, "Path {0} created because does not exists.", logFolder.getAbsolutePath());
		}


		try {
			System.out.println("---1");
			this.jvmDatabaseHandler = new FileJvmHandler(dataFolder.getAbsolutePath() + File.separator, jvmSamplingPeriod);
			System.out.println("---2");
			this.httpSessionDatabaseHandler = new FileHttpSessionHandler(dataFolder.getAbsolutePath() + File.separator, httpSessionSamplingPeriod);
			System.out.println("---3");
			this.hardDiskDatabaseHandler = new FileHardDiskHandler(dataFolder.getAbsolutePath() + File.separator, hardDiskSamplingPeriod);
			System.out.println("---4");
			this.actionDatabaseHandler = new FileActionHandler(dataFolder.getAbsolutePath() + File.separator, actionSamplingPeriod);
			System.out.println("---5");
			this.settingsDatabaseHandler = new FileSettingsHandler(settingsFolder.getAbsolutePath() + File.separator);

		} catch (IOException e) {
			throw new DatabaseException("FileDatabaseHandler initialization error.", e);
		}
	}

	//Action
	public void persistActionStatistics(List<ActionCoreElement> invocationsList) throws DatabaseException {

		try {
			this.actionDatabaseHandler.persistStatistics(invocationsList);
		} catch (final IOException e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Error persisting Action statistics.", e);
		}
	}

	public void deleteActionStatistics(ActionParameters.DeleteStatisticsParameter parameters) throws DatabaseException {
		try {
			this.actionDatabaseHandler.deleteStatistics(parameters);
		} catch (final IOException e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Error deleting Action statistics.", e);
		}
	}

	public ResultSetStatistics<ActionStatistics> searchActionStatistics(ActionParameters.SearchStatisticsParameter parameters) throws DatabaseException {
		try {
			return this.actionDatabaseHandler.searchStatistics(parameters);
		} catch (final IOException e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Error searching Action statistics.", e);
		}
	}

	public List<ActionStatistics.Exception> searchActionStatisticsExcepions(ActionParameters.SearchExceptionsParameter parameters) throws DatabaseException {
		throw new UnsupportedOperationException("Not supported yet.");
	}

	public ResultSetElement<ActionStatistics.Element> searchActionElements(ActionParameters.SearchElementsParameter parameters) throws DatabaseException {

		try {
			return this.actionDatabaseHandler.searchElements(parameters);
		} catch (final IOException e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Error searching Action elements.", e);
		}
	}

	//JVM
	public void persistJvmStatistics(List<JvmCoreElement> invocationsList) throws DatabaseException {
		try {
			this.jvmDatabaseHandler.persistStatistics(invocationsList);
		} catch (final IOException e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Error persisting JVM statistics.", e);
		}
	}

	public void deleteJvmStatistics(JvmParameters.DeleteStatisticsParameter parameters) throws DatabaseException {

		try {
			this.jvmDatabaseHandler.deleteStatistics(parameters);
		} catch (final IOException e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Error deleting JVM statistics.", e);
		}
	}

	public ResultSetElement<JvmStatistics.Element> searchJvmElements(JvmParameters.SearchElementsParameter parameters) throws DatabaseException {
		try {
			return this.jvmDatabaseHandler.searchElements(parameters);
		} catch (final Exception e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Error searching JVM elements.", e);
		}


	}

	public ResultSetStatistics<JvmStatistics> searchJvmStatistics(JvmParameters.SearchStatisticsParameter parameters) throws DatabaseException {

		try {
			return this.jvmDatabaseHandler.searchStatistics(parameters);
		} catch (final IOException e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Error searching JVM statistics.", e);
		}


	}

	//Http Session
	public void persistHttpSessionStatistics(List<HttpSessionCoreElement> invocationsList) throws DatabaseException {

		try {
			this.httpSessionDatabaseHandler.persistStatistics(invocationsList);
		} catch (final IOException e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Error persisting Http Session statistics.", e);
		}
	}

	public void deleteHttpSessionStatistics(HttpSessionParameters.DeleteStatisticsParameter parameters) throws DatabaseException {

		try {
			this.httpSessionDatabaseHandler.deleteStatistics(parameters);
		} catch (final IOException e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Error deleting Http Session statistics.", e);
		}
	}

	public ResultSetElement<HttpSessionStatistics.Element> searchHttpSessionElements(HttpSessionParameters.SearchElementsParameter parameters) throws DatabaseException {

		try {
			return this.httpSessionDatabaseHandler.searchElements(parameters);
		} catch (final IOException e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Error searching Http Session elements.", e);
		}
	}

	public ResultSetStatistics<HttpSessionStatistics> searchHttpSessionStatistics(HttpSessionParameters.SearchStatisticsParameter parameters) throws DatabaseException {

		try {
			return this.httpSessionDatabaseHandler.searchStatistics(parameters);
		} catch (final IOException e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Error searching Http session statistics.", e);
		}
	}

	//Hard Disk
	public void persistHardDiskStatistics(List<HardDiskCoreElement> invocationsList) throws DatabaseException {

		try {
			hardDiskDatabaseHandler.persistStatistics(invocationsList);
		} catch (Exception e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Error persisting Hard Disk statistics.", e);
		}
	}

	public void deleteHardDiskStatistics(HardDiskParameters.DeleteStatisticsParameter parameters) throws DatabaseException {

		try {
			this.hardDiskDatabaseHandler.deleteStatistics(parameters);
		} catch (final Exception e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Error deleting Hard Disk statistics.", e);
		}
	}

	public ResultSetElement<HardDiskStatistics.Element> searchHardDiskElements(HardDiskParameters.SearchElementsParameter parameters) throws DatabaseException {

		try {
			return this.hardDiskDatabaseHandler.searchElements(parameters);
		} catch (final Exception e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Error searching Hard Disk elements.", e);
		}
	}

	public ResultSetStatistics<HardDiskStatistics> searchHardDiskStatistics(HardDiskParameters.SearchStatisticsParameter parameters) throws DatabaseException {

		try {
			return this.hardDiskDatabaseHandler.searchStatistics(parameters);
		} catch (final Exception e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Error searching Hard Disk statistics.", e);
		}
	}

	//Settings
	public Settings loadSettings() throws DatabaseException {

		try {
			return this.settingsDatabaseHandler.loadSettings();

		} catch (final ClassNotFoundException e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Unable to load settings entity from table. Read binary object failed.", e);
		} catch (final IOException e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Unable to load settings entity from table.", e);
		}
	}

	public void updateSettings(Settings settings) throws DatabaseException {

		try {
			this.settingsDatabaseHandler.updateSettings(settings);
		} catch (final IOException e) {
			JeeObserverServerContext.logger.log(Level.SEVERE, e.getMessage());
			throw new DatabaseException("Unable to insert/update settings entity into table. Write binary object failed.", e);
		}
	}

	static void fillBuffer(ByteBuffer buffer, SamplingStatistics statistics) {
		buffer.putLong(statistics.getDate().getTime());
		buffer.putInt(statistics.getCount());
	}

	static void fillBuffer(ByteBuffer buffer, DateStatistics statistics) {
		buffer.putLong(statistics.getMinimum().getTime());
		buffer.putLong(statistics.getMaximum().getTime());
	}

	static void fillBuffer(ByteBuffer buffer, NumberStatistics statistics) {
		buffer.putDouble(statistics.getMinimum());
		buffer.putDouble(statistics.getMaximum());
		buffer.putDouble(statistics.getSum());
	}

	static NumberStatistics getNumberStatistics(ByteBuffer buffer, Date date) {
		return new NumberStatistics(date, buffer.getDouble(), buffer.getDouble(), buffer.getDouble());
	}

	static NumberStatistics getNumberStatistics(ByteBuffer buffer, Date date, boolean empty) {
		if (empty) {
			return new NumberStatistics();
		} else {
			return getNumberStatistics(buffer, date);
		}
	}

	static DateStatistics getDateStatistics(ByteBuffer buffer) {
		return new DateStatistics(new Date(buffer.getLong()), new Date(buffer.getLong()));
	}
}
